"use strict";

var router = require("router"),
    TokenService = require("router").TokenService,
    mongo = require('./core/mongoservice'),
    ObjectId = require('mongodb').ObjectID,
    Q = require('q');

function SearchService() {
    console.log("SearchService constructor");
}
SearchService.prototype = Object.create(TokenService.prototype);
SearchService.prototype.constructor = SearchService;

SearchService.prototype.search = function (request, response, promise) {
    return promise.then(function (self) {
        //self.identify(request, response);
        var skip = parseInt(request.query.skip);
        var limit = parseInt(request.query.limit);

        var query = request.query.q;

        return self.mongoSearch(query, { skip: skip, limit: limit }).then(function (results) {
            return response.send({ request: request, content: results });
        });
    });
};

SearchService.prototype.searchShop = function (request, response, promise) {
    return promise.then(function (self) {

        //self.identify(request, response);
        var skip = parseInt(request.query.skip);
        var limit = parseInt(request.query.limit);
        var query = request.query.q;
        return self.mongoSearchShop(query, { skip: skip, limit: limit }).then(function (results) {
            return response.send({ request: request, content: results });
        });
    });
};

SearchService.prototype.searchUser = function (request, response, promise) {
    return promise.then(function (self) {
        //self.identify(request, response);
        var skip = parseInt(request.query.skip);
        var limit = parseInt(request.query.limit);

        var query = request.query.q;

        return self.mongoSearchUser(query, { skip: skip, limit: limit }).then(function (results) {
            return response.send({ request: request, content: results });
        });
    });
};

SearchService.prototype.searchAlert = function (request, response, promise) {
    return promise.then(function (self) {
        //self.identify(request, response);
        var skip = parseInt(request.query.skip);
        var limit = parseInt(request.query.limit);

        var query = request.query.q;

        return self.mongoSearchAlert(query, { skip: skip, limit: limit }).then(function (results) {
            return response.send({ request: request, content: results });
        });
    });
};

SearchService.prototype.searchArchivedAlert = function (request, response, promise) {
    return promise.then(function (self) {
        self.identify(request, response);

        var shopId = request.payload.shop.id;

        var skip = parseInt(request.query.skip);
        var limit = parseInt(request.query.limit);

        var query = request.query.q;

        return self.mongoSearchArchivedAlert(query, shopId, { skip: skip, limit: limit }).then(function (results) {
            return response.send({ request: request, content: results });
        });
    });
};

/*-------------------------------------------------------*/
/*mongo daf*/

SearchService.prototype.mongoSearchShopByPattern = function (pattern, options) {
    if (!pattern) throw new Error("pattern is not defined.");
    var self = this;

    var opts = {};
    options = options || {}
    if (options.limit) opts.limit = options.limit;
    if (options.skip) opts.skip = options.skip;
    opts.sort = { "name": 1 };

    return mongo.find('shops', { tags: { $all: pattern } } , opts).then(function (cursor) {
        return Q.ninvoke(cursor, 'toArray').then(function (shops) {
            return self.createShopPages(shops);
        });
    });
};

SearchService.prototype.mongoSearchUserByPattern = function (pattern, options) {
    if (!pattern) throw new Error("pattern is not defined.");
    var self = this;

    var opts = {};
    options = options || {}
    if (options.limit) opts.limit = options.limit;
    if (options.skip) opts.skip = options.skip;
    opts.sort = {"login": 1};

    return mongo.find('users', { login: { $all: pattern } } , opts).then(function (cursor) {
        return Q.ninvoke(cursor, 'toArray').then(function (users) {
            return self.createUserPages(users);
        });
    });
};

SearchService.prototype.mongoSearchAlertByPattern = function (pattern, options) {
    if (!pattern) throw new Error("pattern is not defined.");
    var self = this;

    var opts = {};
    options = options || {};
    if (options.limit) opts.limit = options.limit;
    if (options.skip) opts.skip = options.skip;
    opts.sort = {"dates.creation": -1};

    return mongo.find('alerts', { tags: { $all: pattern } } , opts).then(function (cursor) {
        return Q.ninvoke(cursor, 'toArray').then(function (alerts) {
            return self.createAlertPages(alerts);
        });
    });
};

SearchService.prototype.mongoSearchAlertArchivedByPattern = function (shopId, pattern, options) {
    if (!shopId) throw new Error("shopId is not defined.");
    if (!pattern) throw new Error("pattern is not defined.");
    var self = this;

    var shopId = new ObjectId(shopId);

    var opts = {};
    options = options || {};
    if (options.limit) opts.limit = options.limit;
    if (options.skip) opts.skip = options.skip;
    opts.sort = { "dates.creation": -1 };

    return mongo.find('alerts.archives', { "shop.id": shopId, tags: { $all: pattern} }, opts).then(function (cursor) {
        return Q.ninvoke(cursor, 'toArray').then(function (alerts) {
            return self.createAlertPages(alerts);
        });
    });
};

SearchService.prototype.mongoAllAlertArchived = function (shopId, options) {
    if (!shopId) throw new Error("shopId is not defined.");
    var self = this;

    var shopId = new ObjectId(shopId); 

    var opts = {};
    options = options || {};
    if (options.limit) opts.limit = options.limit;
    if (options.skip) opts.skip = options.skip;
    opts.sort = {"dates.creation": -1};

    return mongo.find('alerts.archives', {"shop.id": shopId} , opts).then(function (cursor) {
        return Q.ninvoke(cursor, 'toArray').then(function (alerts) {
            return self.createAlertPages(alerts);
        });
    });
};


SearchService.prototype.mongoSearch = function (query, options) {
    if (!query) throw new Error("query is not defined.");
    var self = this;

    options = options || {};
    options.skip = options.skip || 0;
    var results = [];

    return require("./tagservice").mongoSplit(query).then(function (res) {
        var pattern = res.reduce(function (previous, current) {
            previous.push(new RegExp("^" + current, "ig"));
            return previous;
        }, []);

        return self.mongoSearchShopByPattern(pattern, options).then(function (results1) {
            results = results1;
            return self.mongoSearchAlertByPattern(pattern, options).then(function (results3) {
                results = results.concat(results3);
                if (results.length > 0 && options.skip == 0)
                    return require("./researchservice").mongoSave(query).then(function () {
                        return results;
                    });
                return results;
            });
        });
    });
}

SearchService.prototype.mongoSearchAlert = function (query, options) {
    if (!query) throw new Error("query is not defined.");
    var self = this;

    return require("./tagservice").mongoSplit(query).then(function (res) {
        var pattern = res.reduce(function (previous, current) {
            previous.push(new RegExp("^" + current, "ig"));
            return previous;
        }, []);
        return self.mongoSearchAlertByPattern(pattern, options);
    });
}

SearchService.prototype.mongoSearchShop = function (query, options) {
    if (!query) throw new Error("query is not defined.");
    var self = this;

    return require("./tagservice").mongoSplit(query).then(function (res) {
        var pattern = res.reduce(function (previous, current) {
            previous.push(new RegExp("^" + current, "ig"));
            return previous;
        }, []);

        return self.mongoSearchShopByPattern(pattern, options);
    });
}

SearchService.prototype.mongoSearchUser = function (query, options) {
    if (!query) throw new Error("query is not defined.");
    var self = this;

    return require("./tagservice").mongoSplit(query).then(function (res) {
        var pattern = res.reduce(function (previous, current) {
            previous.push(new RegExp("^" + current, "ig"));
            return previous;
        }, []);
        return self.mongoSearchUserByPattern(pattern, options);
    });
}

SearchService.prototype.mongoUserAlert = function (query, options) {
    if (!query) throw new Error("query is not defined.");
    var self = this;

    return require("./tagservice").mongoSplit(query).then(function (res) {
        var pattern = res.reduce(function (previous, current) {
            previous.push(new RegExp("^" + current, "ig"));
            return previous;
        }, []);
        return self.mongoSearchUserByPattern(pattern, options);
    });
}

SearchService.prototype.mongoSearchArchivedAlert = function (query, shopId, options) {
    var self = this;
    var promise = null;

    if (query) {
        return require("./tagservice").mongoSplit(query).then(function (res) {
            var pattern = res.reduce(function (previous, current) {
                previous.push(new RegExp("^" + current, "ig"));
                return previous;
            }, []);

            return self.mongoSearchAlertArchivedByPattern(shopId, pattern, options);
        });
    }
    else {
        return self.mongoAllAlertArchived(shopId, options);
    }
}

/*-------------------------------*/

SearchService.prototype.createAlertPages = function (results) {
    if (!results) throw new Error("results is not defined.");
    var self = this;

    return results.reduce(function (previous, current) {
        previous.push({
            type: "alert",
            obj: current
        });
        return previous;
    }, []);
}

SearchService.prototype.createShopPages = function (results) {
    if (!results) throw new Error("results is not defined.");
    var self = this;

    return results.reduce(function (previous, current) {
        previous.push({
            type: "shop",
            obj: current
        });
        return previous;
    }, []);
}

SearchService.prototype.createUserPages = function (results) {
    if (!results) throw new Error("results is not defined.");
    var self = this;

    return results.reduce(function (previous, current) {
        previous.push({
            type: "user",
            obj: current
        });
        return previous;
    }, []);
}


exports = module.exports = new SearchService();